﻿using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Red.Controls.Depot.FileViewItemsProviders;
using Red.Controls.ViewModels;
using Red.Core;
using Red.Core.Containers;
using Red.Core.Extensions;
using Red.Core.SourceControl;

namespace Red.Controls.Depot.ViewModels
{
    public abstract class DepotTreeItem : RedTreeItem
    {
        #region Data

        private bool _isReadOnly;
        protected static readonly Canvas _folderIcon;
        protected static readonly Canvas _folderOpenIcon;
        protected DepotInfo _depot;

        #endregion Data

        #region C-tor

        public DepotTreeItem( string title, string toolTip, Canvas image, DepotTreeItem parent, DepotInfo depot )
            : base( parent, title, toolTip, image )
        {
            _depot = depot;
        }

        static DepotTreeItem()
        {
            _folderIcon = (Canvas)Application.Current.FindResource( "appbar_folder" );
            _folderOpenIcon = (Canvas)Application.Current.FindResource( "appbar_folder_open" );
        }

        #endregion C-tor

        #region Properties

        /// <summary>
        ///     The path to be displayed in a breadcrumb bar
        /// </summary>
        public abstract string BreadcrumbPath { get; }

        public virtual string ShortName { get { return Title; } }

        #endregion Properties

        #region Interface
        
        public abstract FileViewItemsProvider GetItemsProvider();

        #endregion Interface

    }

    /// <summary>
    ///     Invisible tree root item
    /// </summary>
    public class DepotTreeItemRoot : DepotTreeItem
    {
        #region Data

        private List<DepotTreeItemDirectoryRoot> _depotEntryPoints = new List<DepotTreeItemDirectoryRoot>();
        private DepotTreeItemChangelistRoot _clRoot;
        private DepotTreeItemFavoriteRoot _favRoot;
        private DepotTreeItemAssetsRoot _assetsRoot;
        private bool _showAssetView = false;

        #endregion Data

        #region Properties

        public override string BreadcrumbPath { get { return ""; } }

        public Monitor Monitor { get; private set; } = new Monitor();

        public DepotInfo Depot
        {
            get { return _depot; }

            set
            {
                if ( _depot != value )
                {
                    Monitor.SourceControl = value?.SourceControl;
                    _depot = value;
                    RebuildRoots().DoNotAwait();
                }
            }
        }

        public bool ShowAssetView
        {
            get { return _showAssetView; }

            set
            {
                if ( _showAssetView != value )
                {
                    _showAssetView = value;
                    RebuildRoots().DoNotAwait();
                }
            }
        }

        public IEnumerable<string> Favorites
        {
            get { return _favRoot.Favorites; }
            set { _favRoot.Favorites = value; }
        }

        #endregion Properties

        #region C-tor

        public DepotTreeItemRoot()
            : base( "", "", null, null, null )
        {
            Monitor.Changelist += Monitor_ChangelistModified;
        }

        #endregion C-tor

        #region DepotTreeItem implementation

        public override FileViewItemsProvider GetItemsProvider()
        {
            return new EmptyItemsProvider();
        }

        #endregion DepotTreeItem implementation

        #region LazyHierarchicalItem implementation

        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();

            children.Add( _favRoot );
            children.Add( _clRoot );
            children.AddRange( _depotEntryPoints );
            if ( _assetsRoot != null )
                children.Add( _assetsRoot );

            return Task.CompletedTask;
        }

        #endregion LazyHierarchicalItem implementation

        #region Private methods

        private async Task RebuildRoots()
        {
            if ( _depot != null )
            {
                _favRoot = new DepotTreeItemFavoriteRoot( this, _depot );
                _clRoot = new DepotTreeItemChangelistRoot( this, _depot );
                if ( _showAssetView )
                    _assetsRoot = new DepotTreeItemAssetsRoot( this, _depot );
                _depotEntryPoints.Clear();
                foreach ( var entryPoint in _depot.EntryPoints )
                {
                    var path = System.IO.Path.Combine( _depot.RootPath, entryPoint.Path );
                    var info = new DirectoryInfo( path );
                    _depotEntryPoints.Add( new DepotTreeItemDirectoryRoot( info, entryPoint.Path, this, _depot, entryPoint.IsReadOnly ) );
                }
                await RebuildAsync();
                if ( _depotEntryPoints.Count > 0 )
                    _depotEntryPoints[ 0 ].IsExpanded = true;
            }
            else
            {
                _favRoot = null;
                _clRoot = null;
                _assetsRoot = null;
                _depotEntryPoints.Clear();
            }

        }

        #endregion Private methods

        #region Event handlers
        
        private async void Monitor_ChangelistModified( int changelistId )
        {
            await _clRoot.RebuildAsync();
        }

        #endregion Event handlers
    }
}